package com.henan.caigou.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.henan.caigou.entity.Contract;
import com.henan.caigou.vo.ContractVo;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class HenanCaigouCrawlerService {
    private static final String BASE_URL = "https://zfcg.henan.gov.cn";
    public static ContractVo start(String url) throws Exception {
        String actionUrl = "";
        String captchaUrl = "";
        Document doc = Jsoup.connect(url).get();
        Element form = doc.selectFirst("form#cgxxForm");

        if (form != null) {
            actionUrl = form.attr("action");
            System.out.println("表单提交地址: " + actionUrl);
            if (!actionUrl.startsWith("http")) {
                actionUrl = "https://zfcg.henan.gov.cn" + actionUrl;
            }
            System.out.println("完整表单提交URL: " + actionUrl);
        }

        // 2. 提取验证码图片地址
        Element captchaImg = doc.selectFirst("img[id=recode]");
        if (captchaImg != null) {
            captchaUrl = captchaImg.attr("src");
            System.out.println("验证码图片地址: " + captchaUrl);

            // 补全为完整URL（如果是相对路径）
            if (!captchaUrl.startsWith("http")) {
                captchaUrl = "https://zfcg.henan.gov.cn" + captchaUrl;
            }
            System.out.println("完整验证码URL: " + captchaUrl);
        }

        String captchaBase64 = downloadAndConvertToBase64(captchaUrl);
        System.out.println("验证码Base64字符串: " + captchaBase64);
        String code = ocrCode(captchaBase64);

        Document docCode = Jsoup.connect(actionUrl)
                .data("code", code)
                .header("Content-Type", "application/x-www-form-urlencoded")
                .timeout(120000)
                .post();

        int responseCode = docCode.connection().response().statusCode();
        System.out.println("响应码: " + responseCode);
        String location = docCode.connection().response().header("Location");
        System.out.println("Location: " + location);


        ContractVo contracts = extractBidInfo(actionUrl);

        if (contracts.getNextPage().isEmpty()) {
            System.out.println("验证码错误，重新获取");
            Thread.sleep(1000);
            return start(url);
        }

        return contracts;
    }

    // 获取详情页
    public static Contract getDetail(String url) throws IOException {
        Document doc = Jsoup.connect(url)
                .userAgent("Mozilla/5.0")
                .timeout(10000)
                .get();

        Contract contract = new Contract();

        // 提取发布机构
        Element publisherElement = doc.selectFirst("div.TxtCenter.BorderTopDot.Gray span.Gray:nth-child(1)");
        if (publisherElement != null) {
            contract.setPublishOrgin(publisherElement.text());
        }

        // 提取发布日期
        Element publishDateElement = doc.selectFirst("div.TxtCenter.BorderTopDot.Gray span.Gray:nth-child(2)");
        if (publishDateElement != null) {
            String publishDateString = publishDateElement.text().replace("发布日期：", "").trim();
            Date publishDate = convertStringToDate(publishDateString);
            contract.setPublishTime(publishDate);
        }

        // 提取附件信息
        Elements attachmentElements = doc.select("div.List1.Top5 ul li a");
        List<String> attachmentUrls = new ArrayList<>();
        List<String> attachmentNames = new ArrayList<>();
        for (Element attachmentElement : attachmentElements) {
            attachmentUrls.add(attachmentElement.attr("href"));
            attachmentNames.add(attachmentElement.text());
        }

        contract.setAttachmentUrl(String.join(",", attachmentUrls));
        contract.setAttachmentName(String.join(",", attachmentNames));

        // 提取动态加载内容的 URL
        Elements scriptElements = doc.select("script");
        String dynamicContentUrl = null;
        for (Element scriptElement : scriptElements) {
            String scriptText = scriptElement.html();
            if (scriptText.contains("$.get")) {
                int start = scriptText.indexOf("\"") + 1;
                int end = scriptText.indexOf("\"", start);
                dynamicContentUrl = scriptText.substring(start, end);
                break;
            }
        }

        if (dynamicContentUrl != null) {
            // 发送 GET 请求获取动态内容
            Document dynamicDoc = Jsoup.connect(BASE_URL + dynamicContentUrl)
                    .userAgent("Mozilla/5.0")
                    .timeout(10000)
                    .get();

            // 将动态内容插入到 #content 元素中
            Element contentElement = doc.getElementById("content");
            if (contentElement != null) {
                contentElement.html(dynamicDoc.body().html());
            }
        }

        // 提取富文本内容
        Element contentElement = doc.getElementById("content");
        if (contentElement != null) {
            contract.setContent(contentElement.html());
        }


        return contract;
    }

    private static String ocrCode(String captchaBase64) throws IOException {
        //注册后用户中心找到token填这儿
        String token= "_kT3Mbkt-2sAkHsVcR2wY04zVQwPb4k-Wo6xlGPcX-4";
        //类型id 产品列表里找自己需要的产品的id,然后改这儿
        String typeid= "10110";
        // 图片二进制流base64字符串
        String image= captchaBase64;
        Map< String, String> data = new HashMap<>();
        data.put("token",token);
        data.put("type", typeid);
        data.put("image", image);

        String resultString = Jsoup.connect("http://api.jfbym.com/api/YmServer/customApi")
                .requestBody(JSON.toJSONString(data))
                .header("Content-Type", "application/json")
                .ignoreContentType(true).timeout(120000).post().text();
        JSONObject jsonObject = JSONObject.parseObject(resultString);
        Integer code = jsonObject.getInteger("code");
        if (code==10000) {
            String result=jsonObject.getJSONObject("data").getString("data");
            System.out.println("识别成功结果为:"+result);
            return result;
        }else {
            System.out.println("识别失败原因为:"+jsonObject.getString("msg"));
            return "";
        }
    }

    /**
     * 下载验证码图片并转换为Base64字符串
     */
    private static String downloadAndConvertToBase64(String captchaUrl) throws IOException {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(captchaUrl);
            CloseableHttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();

            if (entity != null) {
                // 将实体内容读取到字节数组
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                entity.writeTo(baos);
                byte[] bytes = baos.toByteArray();

                // 转换为Base64字符串
                String base64String = Base64.encodeBase64String(bytes);
                return base64String;
            }
        }
        return "";
    }


    public static ContractVo extractBidInfo(String url) throws IOException {
        ContractVo contractVo = new ContractVo();
        List<Contract> contractList = new ArrayList<>();
        contractVo.setList(contractList);

        Document doc = Jsoup.connect(url)
                .userAgent("Mozilla/5.0")
                .timeout(10000)
                .get();

        // 2. 定位列表区域
        Elements items = doc.select("div.List2 ul li");
        // 获取下一页地址
        Element nextPage = doc.selectFirst("li.nextPage > a");
        if (nextPage != null) {
            System.out.println("下一页地址: " + nextPage.attr("href"));
            String baseUrl = BASE_URL + "/henan/";
            String fullUrl = baseUrl + nextPage.attr("href");
            System.out.println("完整下一页URL: " + fullUrl);
            contractVo.setNextPage(fullUrl);
        }

        // 3. 遍历每个招标项
        for (Element item : items) {
            Contract contract = new Contract();

            // 提取标题和链接
            Element titleLink = item.selectFirst("a");
            contract.setTitle(titleLink.text());
            contract.setUrl(titleLink.attr("href"));
            String href = titleLink.attr("href");
            if (href.contains("infoId=")) {
                String infoIdStr = href.substring(href.indexOf("infoId=") + 7, href.indexOf("&channelCode"));
                contract.setInfoId(Integer.valueOf(infoIdStr));
            }

            // 提取公告类型、区域、采购人
            Elements spans = item.select("p span");
            for (Element span : spans) {
                String text = span.text();
                if (text.startsWith("公告类型：")) {
                    contract.setType(span.selectFirst(".Blue").text());
                } else if (text.startsWith("区域：")) {
                    contract.setRegion(span.selectFirst(".Blue").text());
                } else if (text.startsWith("采购人：")) {
                    contract.setPurchaser(span.selectFirst(".Blue").text());
                } else if (text.contains("发布时间：")) {
                    Date date = convertStringToDate(span.selectFirst(".Gray").text().replace("发布时间：", ""));
                    contract.setPublishTime(date);
                }
            }

            contractList.add(contract);
        }
        System.out.println(contractVo);
        return contractVo;
    }

    public static Date convertStringToDate(String dateString) {
        List<SimpleDateFormat> dateFormats = Arrays.asList(
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
                new SimpleDateFormat("yyyy-MM-dd HH:mm"),
                new SimpleDateFormat("yyyy-MM-dd")
        );

        for (SimpleDateFormat formatter : dateFormats) {
            try {
                return formatter.parse(dateString);
            } catch (ParseException e) {

            }
        }

        // 如果所有格式都无法解析，则打印错误信息并返回 null
        System.err.println("无法解析日期字符串: " + dateString);
        return null;
    }
}